﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Json;
using Heimdallr.Net;

/*
 * This is a client application which is receiving chat message via HTTP multipart stream.
 */

namespace Heimdallr.Sample.ChatRoom.Client
{
    class Program
    {
        internal static readonly Uri ServerRequestUri;
        internal static readonly Uri ServerResponseUri;
        internal static readonly DataContractJsonSerializer JsonSerializer;

        static Program()
        {
            UriBuilder uri = new UriBuilder(Uri.UriSchemeHttp, GetLocalIPAddress().ToString(), 80);

            uri.Path = "svc-bin/chatroom/request/";
            ServerRequestUri = uri.Uri;
            uri.Path = "svc-bin/chatroom/response/";
            ServerResponseUri = uri.Uri;

            JsonSerializer = new DataContractJsonSerializer(typeof(Message));
        }

        static void Main(string[] args)
        {
            Console.WriteLine(ServerRequestUri);
            Console.WriteLine(ServerResponseUri);

            HttpMultipartTriggerElement trigger = new HttpMultipartTriggerElement(ServerResponseUri);

            trigger.Notify += trigger_Notify;
            trigger.Error += trigger_Error;
            trigger.StatusChanged += trigger_StatusChanged;

            ServiceElementController<HttpMultipartTriggerElement> controller = new ServiceElementController<HttpMultipartTriggerElement>(trigger);

            controller.Start();

            Console.WriteLine("Enter message or 'exit' to leave...");

            while (true)
            {
                string message = Console.ReadLine();

                if (message.ToLowerInvariant() == "exit")
                    break;

                HttpWebRequest request = HttpWebRequest.Create(ServerRequestUri) as HttpWebRequest;

                request.Method = WebRequestMethods.Http.Post;
                request.ContentType = "application/json";

                try
                {
                    using (Stream stream = request.GetRequestStream())
                        JsonSerializer.WriteObject(stream, new Message()
                        {
                            Text = message,
                            Name = Environment.MachineName
                        });

                    using (WebResponse response = request.GetResponse())
                        response.Close();
                }
                catch (Exception error)
                {
                    Console.WriteLine(error);
                }
            }

            controller.Stop();
        }

        static void trigger_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            Console.WriteLine("Chat Room Client Status: {0} -> {1}", e.OldStatus, e.NewStatus);
        }

        static void trigger_Error(object sender, ExceptionsEventArgs e)
        {
            Console.WriteLine("Chat Room Client Error(s): ");
            Console.WriteLine(e);
        }

        static void trigger_Notify(object sender, FireNotificationEventArgs e)
        {
            Message message;

            using (Stream stream = e.Notification.CreateReadOnlyStream())
                message = JsonSerializer.ReadObject(stream) as Message;

            Console.WriteLine("Incoming message: {0} - {1}", message.Text, e.Notification.Time);
        }

        static IPAddress GetLocalIPAddress()
        {
            IPAddress result = Dns.GetHostAddresses(Dns.GetHostName()).FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);

            if (result == null)
                return IPAddress.Loopback;
            else
                return result;
        }
    }
}